import java.awt.Color;
import java.awt.GraphicsConfiguration;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;

import javax.media.j3d.Appearance;
import javax.media.j3d.BoundingSphere;
import javax.media.j3d.BranchGroup;
import javax.media.j3d.Canvas3D;
import javax.media.j3d.ColoringAttributes;
import javax.media.j3d.DirectionalLight;
import javax.media.j3d.QuadArray;
import javax.media.j3d.Shape3D;
import javax.media.j3d.Transform3D;
import javax.media.j3d.TransformGroup;
import javax.swing.JFrame;
import javax.vecmath.AxisAngle4d;
import javax.vecmath.Color3f;
import javax.vecmath.Point3d;
import javax.vecmath.Point3f;
import javax.vecmath.Vector3f;

import com.sun.j3d.utils.geometry.Box;
import com.sun.j3d.utils.geometry.Primitive;
import com.sun.j3d.utils.picking.PickCanvas;
import com.sun.j3d.utils.picking.PickResult;
import com.sun.j3d.utils.universe.SimpleUniverse;


public class LegoBrickTest extends JFrame {

    
	private static final long serialVersionUID = 1L;
	private final int WINDOW_HEIGHT = 700;
	private final int WINDOW_WIDTH = 600;
	
	protected BranchGroup mainBranchGroup;
	private PickCanvas pickCanvas;
	
	public LegoBrickTest() {
		super("Saarland University - Lego3D GUI Concept");
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setResizable(false);
		
		////////
		/// Setup Universe
		
		GraphicsConfiguration config = SimpleUniverse.getPreferredConfiguration();

	    Canvas3D canvas = new Canvas3D(config);

	    canvas.setSize(WINDOW_HEIGHT, WINDOW_WIDTH);

		   // Create the universe
		   SimpleUniverse universe = new SimpleUniverse(canvas);
		   this.add(canvas);
		   // Create a structure to contain objects
		   mainBranchGroup = new BranchGroup();
		   mainBranchGroup.setCapability(BranchGroup.ALLOW_CHILDREN_WRITE); 
		   mainBranchGroup.setCapability(BranchGroup.ALLOW_CHILDREN_READ);
		   mainBranchGroup.setCapability(BranchGroup.ALLOW_CHILDREN_EXTEND);
		   
		////////
		/// Create stuff in the group
		   
		   // Create a ball and add it to the group of objects
		   Appearance polygon1Appearance = new Appearance();
		   QuadArray polyBottom = new QuadArray (4, QuadArray.COORDINATES);
		   polyBottom.setCoordinate (0, new Point3f (-1.5f, 0f, 0f));
		   polyBottom.setCoordinate (1, new Point3f (1.5f, 0f, 0f));
		   polyBottom.setCoordinate (2, new Point3f (1.5f, 0f, -3.0f));
		   polyBottom.setCoordinate (3, new Point3f (-1.5f, 0f, -3.0f));
		   mainBranchGroup.addChild(new Shape3D(polyBottom,polygon1Appearance));
		   
		////////
		/// Lights
		   
		   // Create a red light that shines for 100m from the origin
		   Color3f light1Color = new Color3f(1f, 1f, 1f); //Farbe des Lichts
		   BoundingSphere bounds = new BoundingSphere(new Point3d(0.0,0.0,0.0), 100.0); //Aktionsbereichs des Lichts
		   Vector3f light1Direction = new Vector3f(0f, -1f, -1f); //Richtung
		   DirectionalLight light1 = new DirectionalLight(light1Color, light1Direction); //Setzen
		   light1.setInfluencingBounds(bounds); //Setzen
		   mainBranchGroup.addChild(light1); //fertig


	    ////////
		/// Camera ViewPoint

		   // Set camera position
		   Vector3f translateP = new Vector3f();
		   Transform3D T3DS = new Transform3D();
		   TransformGroup tgVaizS = null;
		   tgVaizS = universe.getViewingPlatform().getViewPlatformTransform();
		   translateP.set(0.0f, 4.0f, 1.0f);
		   T3DS.setRotation(new AxisAngle4d(-1, 0, 0, Math.toRadians(60)));
		   T3DS.setTranslation(translateP);
		   tgVaizS.setTransform(T3DS);
		   
		   LegoBrick3D brick = new LegoBrick3D(Color.PINK.getRGB(), 1, 1,2);
		   
		   universe.addBranchGraph(mainBranchGroup);

		   pickCanvas = new PickCanvas(canvas, mainBranchGroup);
		   pickCanvas.setMode(PickCanvas.BOUNDS);
			
		   canvas.addMouseListener(new MouseHandler());
		   
		   this.pack();
		   this.setVisible(true);
	}

	public static void main( String[] args ) {
	   new LegoBrickTest();
	}
	
	private class MouseHandler implements MouseListener {

		private LegoBrick3D selectedBrick = null;
		
		
		@Override
		public void mouseClicked(MouseEvent e) {

		}

		@Override
		public void mouseEntered(MouseEvent e) {
			// TODO Auto-generated method stub
			
		}

		@Override
		public void mouseExited(MouseEvent e) {
			// TODO Auto-generated method stub
			
		}

		@Override
		public void mousePressed(MouseEvent e) {
			pickCanvas.setShapeLocation(e);

		    PickResult result = pickCanvas.pickClosest();

		    if (result == null) {
		       System.out.println("Nothing picked");
		       selectedBrick = null;
		    } else {
		       Primitive p = (Primitive)result.getNode(PickResult.PRIMITIVE);
		       if (p != null) {
		          System.out.println(p.getParent().getParent().getParent().getName());
		          selectedBrick = (LegoBrick3D) p.getParent().getParent().getParent();
		       } else {
		    	  System.out.println("No brick selected");
		    	  selectedBrick = null;
		       }
		    }
		}

		@Override
		public void mouseReleased(MouseEvent e) {
			// TODO Auto-generated method stub
			
		}
		
	}
	
	private class LegoBrick3D extends BranchGroup {
		
		private int rotation = 0;
		
		private TransformGroup transformGroup = new TransformGroup();
		private Transform3D T3D = new Transform3D();
		
		public LegoBrick3D(int color, int height, int ... size) {
			Transform3D T3D;
			TransformGroup transformGroup;
			this.transformGroup.setCapability(BranchGroup.ALLOW_DETACH);
			setCapability(BranchGroup.ALLOW_CHILDREN_WRITE);
			setCapability(BranchGroup.ALLOW_CHILDREN_READ);
			setCapability(BranchGroup.ALLOW_DETACH);
			
			setName("Ich bin ein ganzer LegoBrick");
			
			//color 
			ColoringAttributes coloring = new ColoringAttributes();
			coloring.setColor(new Color3f(new Color(color)));
			Appearance app = new Appearance();
			app.setColoringAttributes(coloring);
			
			//Create main box
			Box basicbox = new Box(size.length/2f*0.1f, height/2f * 0.15f, 0.05f, app);
			basicbox.setName("MainBox");

			//And move it
			T3D = new Transform3D();
			T3D.setTranslation(new Vector3f(size.length/2f*0.1f, height/2f*0.1f, 0f));
			transformGroup = new TransformGroup(T3D);
			transformGroup.addChild(basicbox);
			
			//Add to private transformgroup
			this.transformGroup.addChild(transformGroup);
			
			for (int i = 0; i < size.length; i++) {
				if (size[i] > 1) {
					Box depthbox = new Box(0.05f, height/2f * 0.15f, (size[i]-1)/2f*0.1f, app);
					depthbox.setName("DepthBox_"+i);
					
					T3D = new Transform3D();
					T3D.setTranslation(new Vector3f(i*0.1f + 0.05f, height/2f*0.1f, 0.05f + ((size[i]-1)/2f * 0.1f)));
					
					transformGroup = new TransformGroup(T3D);
					transformGroup.addChild(depthbox);
					
					this.transformGroup.addChild(transformGroup);
				}
			}
			this.addChild(this.transformGroup);
			mainBranchGroup.addChild(this);
		}
		
		public void move(float x, float y, float z) {
			mainBranchGroup.removeChild(this);
			this.removeChild(this.transformGroup);
			Vector3f old = new Vector3f();
			this.T3D.get(old);
			this.T3D.setTranslation(new Vector3f(old.x + (x*0.1f), old.y + (y*0.1f), old.z +(z*0.1f)));
			this.transformGroup.setTransform(this.T3D);
			this.addChild(this.transformGroup);
			mainBranchGroup.addChild(this);
		}
		
		public void rotate(boolean left) {
			
			if (left) {
				this.rotation += 90;
				this.rotation = (this.rotation == 360) ? 0 : this.rotation;
			} else {
				this.rotation -= 90;
				this.rotation = (this.rotation == -90) ? 270 : this.rotation;
			}
			
			mainBranchGroup.removeChild(this.transformGroup);
			this.T3D.setRotation(new AxisAngle4d(0, 1, 0, Math.toRadians(this.rotation)));
			this.transformGroup.setTransform(this.T3D);
			mainBranchGroup.addChild(this.transformGroup);
		}
	}
	
}




